#ifndef OPERAND_H
#define OPERAND_H
#include <set>
#include <cassert>
#include <iostream>
#include <algorithm>
#include "types.h"
#include "Graph.h"

using namespace std;

enum class OperandType : unsigned int{
    CHAR,
    CHARSET,
    REGULAR,
};

class Operand{
public:
    virtual OperandType get_operand_type()=0;
    virtual string get_info() const =0 ;
    virtual Graph *get_graph()=0;
};

class CharOperand : public Operand{
private:
    set<char> charset;
public:
    Graph pNFA;
    enum class CharType :unsigned int{
        NUMBER, //0~9
        LOWERCASE,//a~z
        BIGGERCASE,//A~Z
        OtherType,
    };
    static CharType get_char_type(char ch){
        if('0'<=ch &&ch<='9'){
            return CharType::NUMBER;
        }else if('a'<=ch &&ch<='z'){
            return CharType::LOWERCASE;
        }else if('A'<=ch &&ch<='Z'){
            return CharType::BIGGERCASE;
        }else{
            return CharType::OtherType;
        }
    }



    CharOperand(){
        pNFA.init_state(charset);
    }
    CharOperand(char ch){
        charset.insert(ch);
        pNFA.init_state(charset);
    }
    CharOperand(set<char> ch_set){
        charset=move(ch_set);
        pNFA.init_state(charset);
    }
    CharOperand(char from_char , char to_char){
        //只允许0～9  a~z  A~Z
        CharType type_one=get_char_type(from_char);
        assert(type_one!=CharType::OtherType);
        assert(type_one==(get_char_type(to_char)));
        for(;from_char<=to_char;from_char++){
            charset.insert(from_char);
        }
        pNFA.init_state(charset);

    };


        // 重载 == 运算符
    bool operator==(const CharOperand& other) const {
        if (charset.size() == other.charset.size() && std::equal(charset.begin(), charset.end(), other.charset.begin())) {
            return true;
        } else {
            return false;
        }
    }
            // 重载 < 运算符
    bool operator<(const CharOperand& other) const {
        if (this->charset.size() != other.charset.size()) {
            return this->charset.size() < other.charset.size();
        } else if(charset.size()!=0){
            return (*this->charset.begin()) < ( *other.charset.begin());
        }else{
            return false;
        }
    }

    OperandType get_operand_type()override{
        if(charset.size()==1){
            return OperandType::CHAR;
        }else{
            return OperandType::CHARSET;
        }
    };

    std::set<char>  get_operand_set(){
        return charset;
    };

    static CharOperand union_operate(CharOperand *oper_one ,CharOperand *oper_two){
        auto oper_charset_one=oper_one->get_operand_set();
        auto oper_charset_two=oper_two->get_operand_set();
        set<char> res_set;
        merge(oper_charset_one.begin(), oper_charset_one.end(), oper_charset_two.begin(), oper_charset_two.end(), std::inserter(res_set, res_set.begin()));
        return CharOperand(res_set);
    };

    void difference_operate(char a){
        //差运算
        if(charset.count(a)){
            charset.erase(a);
        }
    }


    string get_info() const override{

        string res="[";
        for(char ch:charset){
            res+=(ch);
        }
        return res+"]";
        
    };
    Graph *get_graph(){
        return &pNFA;
    }
};

#endif